using System;
using System.IO;
using System.Runtime.CompilerServices;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Model;

namespace UtilZ.Dotnet.Ex.Communication.Base
{
    /// <summary>
    /// 通信客户端基类
    /// </summary>
    public abstract class ClientAbs : IClient
    {
        /// <summary>
        /// 始化参数
        /// </summary>
        protected IClientInitPara _initPara;

        /// <summary>
        /// summary
        /// </summary>
        public IClientInitPara InitPara
        {
            get { return this._initPara; }
        }



        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="initPara">始化参数</param>
        public ClientAbs(IClientInitPara initPara)
        {
            if (initPara == null)
            {
                throw new ArgumentNullException(nameof(initPara));
            }

            this._initPara = initPara;
        }


        /// <summary>
        /// 获取指示当前客户端与服务端口的连接状态
        /// </summary>
        public abstract bool Connected
        {
            get;
        }

        /// <summary>
        /// Tag
        /// </summary>
        public object Tag { get; set; }





        private long _lastSendDataTimestamp = 0L;
        /// <summary>
        /// 获取最后一次发送数据时间戳
        /// </summary>
        public long LastSendDataTimestamp
        {
            get { return this._lastSendDataTimestamp; }
        }
        /// <summary>
        /// 更新最后一次发送数据时间戳
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        protected void UpdateLastSendDataTimestamp()
        {
            this._lastSendDataTimestamp = TimeEx.GetTimestamp();
        }




        private long _lastReceiveDataTimestamp = 0L;
        /// <summary>
        /// 获取最后一次接收到数据的时间戳
        /// </summary>
        public long LastReceiveDataTimestamp
        {
            get { return this._lastReceiveDataTimestamp; }
        }
        /// <summary>
        /// 更新最后一次接收到数据的时间戳
        /// </summary>
#if !NET4_0
        [MethodImpl(MethodImplOptions.AggressiveInlining)]
#endif
        protected void UpdateLastReceiveDataTimestamp()
        {
            this._lastReceiveDataTimestamp = TimeEx.GetTimestamp();
        }






        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="bufferData">发送的数据</param>
        /// <param name="options">发送选项</param>
        public void Send(DataSource bufferData, ISendOptions options)
        {
            this.PrimitiveSend(bufferData, options);
        }

        private byte[] _buffer = null;
        private Stream _bufferStream = null;
        private BinaryWriter _bufferWriter = null;
        private DataSource _bufferData = null;
        private readonly object _bufferLock = new object();
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="data">要发送的数据对象</param>
        /// <param name="options">发送选项</param>
        public void Send(TransferDataAbs data, ISendOptions options)
        {
            lock (this._bufferLock)
            {
                long length = data.GetBufferLength();
                if (this._buffer == null || _buffer.Length < length)
                {
                    this._buffer = new byte[length];
                    if (this._bufferStream != null)
                    {
                        this._bufferStream.Dispose();
                        this._bufferWriter.Dispose();
                    }
                    this._bufferStream = new MemoryStream(this._buffer);
                    this._bufferWriter = new BinaryWriter(this._bufferStream);
                    this._bufferData = new DataSource(this._buffer);
                }

                this._bufferWriter.BaseStream.Position = 0L;
                this._bufferData.Update(0, length);
                data.ToBufferData(this._bufferData, this._bufferWriter);
                this.Send(this._bufferData, options);
            }
        }

        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="bufferData">要发送的数据对象</param>
        /// <param name="options">发送选项</param>
        protected abstract void PrimitiveSend(DataSource bufferData, ISendOptions options);



        /// <summary>
        /// 
        /// </summary>
        protected readonly object _disposeLock = new object();

        /// <summary>
        /// 对象释放标识[true:已释放;false:未释放]
        /// </summary>
        protected bool _disposed = false;
        /// <summary>
        /// 获取当前对象是否已释放[true:已释放;false:未释放]
        /// </summary>
        public bool Disposed
        {
            get
            {
                return _disposed;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        public void Dispose()
        {
            lock (this._disposeLock)
            {
                if (this._disposed)
                {
                    return;
                }
                this._disposed = true;

                this.Dispose(true);
                this._initPara = null;

                GC.SuppressFinalize(true);

            }
        }

        /// <summary>
        /// Dispose
        /// </summary>
        /// <param name="disposing"></param>
        protected virtual void Dispose(bool disposing)
        {

        }
    }
}
